package com.huiyujiaoyu.http;

import android.content.Context;


import com.huiyujiaoyu.base.AppConfig;
import com.huiyujiaoyu.http.httputil.ApiException;
import com.huiyujiaoyu.http.httputil.OkHttpUtil;
import com.huiyujiaoyu.http.httputil.ProgressSubscriber;
import com.huiyujiaoyu.http.httputil.SubscriberListener;
import com.huiyujiaoyu.powertime.model.FileBean;
import com.huiyujiaoyu.powertime.model.IndexItemModel;
import com.huiyujiaoyu.powertime.model.LoginBean;
import com.huiyujiaoyu.powertime.model.SimpleBean;
import com.huiyujiaoyu.powertime.model.SimpleList2Bean;
import com.huiyujiaoyu.powertime.model.SimpleListBean;
import com.huiyujiaoyu.powertime.model.UserInfoBean;
import com.huiyujiaoyu.util.AppUtil;
import com.huiyujiaoyu.util.Constant;
import com.huiyujiaoyu.util.File2Code;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import org.reactivestreams.Subscriber;

import java.io.File;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.internal.disposables.ListCompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subscribers.ResourceSubscriber;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


import static android.R.attr.data;
import static android.R.attr.type;
import static com.huiyujiaoyu.http.HttpApi.BASE_URL;
import static com.huiyujiaoyu.util.AppUtil.AndroidId;
import static com.huiyujiaoyu.util.AppUtil.IMEI;
import static com.huiyujiaoyu.util.AppUtil.WlanMacId;
import static com.huiyujiaoyu.util.Constant.KEY_CODE;
import static com.huiyujiaoyu.util.Constant.PAGE_SIZE;
import static com.huiyujiaoyu.util.Md5Util.strToMd5_32;


/**
 * Created by yujunlong on 2016/8/24.
 */

public class HttpMethods {
    private static final int HTTP_SUCCESS = 200;
    private static final int HTTP_SUCCESS2 = 201;
    private Retrofit retrofit;
    private HttpService httpService;
    private OkHttpClient okhttpclient;
    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        retrofit = getRetrofit(getOkHttpClient(), BASE_URL);
        httpService = retrofit.create(HttpService.class);
    }

    public OkHttpClient getOkHttpClient() {
        if(okhttpclient==null){
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            OkHttpUtil.setHttpConfig(httpClientBuilder);
            if (!AppConfig.EXTERNAL_RELEASE) {
                //设置log拦截器
                httpClientBuilder.addInterceptor(OkHttpUtil.getInterceptor(0));
            }
            okhttpclient =  httpClientBuilder.build();
        }
        return okhttpclient;
    }


    public Retrofit getRetrofit(OkHttpClient client, String baseUrl) {
        return new Retrofit.Builder()
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(baseUrl)
                .build();

    }


    //在访问HttpMethods时创建单例
    private static class SingletonHolder {
        private static final HttpMethods INSTANCE = new HttpMethods();
    }

    //获取单例
    public static HttpMethods getInstance() {
        return SingletonHolder.INSTANCE;
    }


    //添加线程管理并订阅
    private void toSubscribe(Flowable o, Subscriber s) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }
    /**
     * 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber
     *
     * @param <T> Subscriber真正需要的数据类型，也就是Data部分的数据类型
     */
    private class HttpResultFunc<T> implements Function<HttpResult<T>, T> {
        @Override
        public T apply(HttpResult<T> httpResult) throws Exception {
            if (httpResult.status !=HTTP_SUCCESS&&httpResult.status!=HTTP_SUCCESS2) {//0失败 1成功，2 异常
                throw new ApiException(httpResult.status, httpResult.message);
            }
            if(httpResult.data==null){
                httpResult.data = (T) "";
            }
            return httpResult.data;

        }
    }
    //加密
    public static String getMD5Pare(TreeMap<String,Object> map){
        StringBuilder sb = new StringBuilder();
        Set<String> strings = map.keySet();
        Iterator<String> iter = strings.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            sb.append(key+"="+map.get(key));
        }
        return strToMd5_32("nlsg" +  sb.toString() + KEY_CODE);
    }

    //添加公共参数
    public TreeMap addPublicParams(Map<String,Object> params){
        TreeMap<String,Object> map = new TreeMap<>(new Comparator<String>() {
            public int compare(String obj1, String obj2) {
                // 降序排序
                return obj1.compareTo(obj2);
            }
        });
        map.putAll(params);
        map.put("user_id", UserInfoBean.getInstance().getUid());
        map.put("timestamp", System.currentTimeMillis());
        map.put("mobile_type", 1); //
        map.put("mobile_code", strToMd5_32(IMEI() + AndroidId() + WlanMacId())); //
        map.put("code", getMD5Pare(map));
        return map;
    }
    public TreeMap addPublicParams(){
        TreeMap<String,Object> map = new TreeMap<>(new Comparator<String>() {
            public int compare(String obj1, String obj2) {
                // 降序排序
                return obj1.compareTo(obj2);
            }
        });
       map.put("user_id", UserInfoBean.getInstance().getUid());
        map.put("timestamp", System.currentTimeMillis());
        map.put("mobile_type", 1); //
        map.put("mobile_code", strToMd5_32(IMEI() + AndroidId() + WlanMacId())); //
        map.put("code", getMD5Pare(map));
        return map;
    }
    //上传多张图片，文件，单张图片，单个语音等
    public void uploadFile(Context c, ResourceSubscriber<FileBean> subscriber, Map<String,Integer> par, List<File> files, File picfile, File voiceFile) {
        LinkedHashMap<String, RequestBody> bodyMap = new LinkedHashMap<>();
        if(files!=null&&files.size()>0){
            for (int i = 0; i < files.size(); i++) {
                bodyMap.put("pic"+"["+i+"]\"; filename=\""+files.get(i).getName(),RequestBody.create(MediaType.parse(Constant.IMG_MEDIATYPE),files.get(i)));
            }
        }
        if (voiceFile != null) {
            bodyMap.put("fileVoice\"; filename=\"" + voiceFile.getName(), RequestBody.create(MediaType.parse(Constant.MULTIPART_FORM_DATA), voiceFile));
        }
        if(picfile!=null){
            bodyMap.put("pic\"; filename=\""+picfile.getName(),RequestBody.create(MediaType.parse(Constant.IMG_MEDIATYPE),picfile));
        }
        Flowable observable = httpService.uploadfile(AppUtil.getCurrentVersion(c).versionCode + "",par,bodyMap);
        toSubscribe(observable, subscriber);
    }
    public void uploadFile(Context c, ResourceSubscriber<FileBean> subscriber, Map<String,Integer> par, File picfile, File voiceFile) {
        LinkedHashMap<String, RequestBody> bodyMap = new LinkedHashMap<>();
        if(picfile!=null){
            bodyMap.put("pic\"; filename=\""+picfile.getName(),RequestBody.create(MediaType.parse(Constant.IMG_MEDIATYPE),picfile));
        }
        if (voiceFile != null) {
            bodyMap.put("fileVoice\"; filename=\"" + voiceFile.getName(), RequestBody.create(MediaType.parse(Constant.MULTIPART_FORM_DATA), voiceFile));
        }
        Flowable observable = httpService.uploadfile(AppUtil.getCurrentVersion(c).versionCode + "",par,bodyMap);
        toSubscribe(observable, subscriber);
    }
    public void getVerificationCode(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,
                                    String phone, int type) {
        Map<String,Object> params = new HashMap<>();
        params.put("phone",phone);
        params.put("send_type",type);
        Flowable observable = httpService.getVerificationCode(addPublicParams(params))
                .map(new HttpResultFunc<List<String>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_GETVERIFICATIONCODE);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void login(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,
                                    String phone, String code) {
        Map<String,Object> params = new HashMap<>();
        params.put("phone",phone);
        params.put("verify_code",code);
        Flowable observable = httpService.login(addPublicParams(params))
                .map(new HttpResultFunc<LoginBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_LOGIN);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void update(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,
                       Map<String,Object> params) {
        Flowable observable = httpService.update(addPublicParams(params))
                .map(new HttpResultFunc<List<String>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_UPDATE);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void index(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener) {
        Flowable observable = httpService.index(addPublicParams())
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_INDEX);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void hot(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int content_type,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("page",page);
        params.put("content_type",content_type);
        Flowable observable = httpService.hot(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_HOT,false);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void headlines(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("page",page);
        Flowable observable = httpService.headlines(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_HEADLINES,false);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void view(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content_id,String chapter_id, int type) {
        Map<String,Object> params = new HashMap<>();
        params.put("content_id",content_id);
        params.put("chapter_id",chapter_id);
        params.put("type",type);
        Flowable observable = httpService.view(addPublicParams(params))
                .map(new HttpResultFunc<SimpleBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_VIEW);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void chapters(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content_id,String chapter_id) {
        Map<String,Object> params = new HashMap<>();
        params.put("content_id",content_id);
        params.put("chapter_id",chapter_id);
        Flowable observable = httpService.chapters(addPublicParams(params))
                .map(new HttpResultFunc<List<IndexItemModel>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_CHAPTERS);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void cIndex(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content_id,String column_id,String pid,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("content_id",content_id);
        params.put("column_id",column_id);
        params.put("pid",pid);
        params.put("page",page);
        Flowable observable = httpService.cIndex(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COMMENT_INDEX);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void collect(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content_id) {
        Map<String,Object> params = new HashMap<>();
        params.put("content_id",content_id);
        Flowable observable = httpService.collect(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COLLECT);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void comment(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content_id,String content,int score,int column_id,int pid) {
        Map<String,Object> params = new HashMap<>();
        params.put("content_id",content_id);
        params.put("content",content);
        params.put("score",score);
        params.put("column_id",column_id);
        params.put("pid",pid);
        Flowable observable = httpService.comment(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COM_ADD);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void column(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String dict_key) {
        Map<String,Object> params = new HashMap<>();
        params.put("dict_key",dict_key);
        Flowable observable = httpService.column(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COL_INDEX);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }

    public void find(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String dict_key,String content_type,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("dict_key",dict_key);
        params.put("num",PAGE_SIZE);
        params.put("content_type",content_type);
        params.put("page",page);
        Flowable observable = httpService.find(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_FIND,false);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }

    public void hotkeys(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener) {
        Flowable observable = httpService.hotkeys(addPublicParams())
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_HOTKEYS);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void keywordss(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String keywords,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("keywords",keywords);
        params.put("num",PAGE_SIZE);
        params.put("page",page);
        Flowable observable = httpService.keywordss(addPublicParams(params))
                .map(new HttpResultFunc<SimpleList2Bean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_KEYWORDSS,false);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }

    public void userinfo(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener) {
        Flowable observable = httpService.userinfo(addPublicParams())
                .map(new HttpResultFunc<LoginBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_USERINFO,false);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void message(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("num",PAGE_SIZE);
        params.put("page",page);
        Flowable observable = httpService.message(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_MESSAGES);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }

    public void uploadimg(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int casee,String path ) {
        Map<String,Object> params = new HashMap<>();
        String data = "";
        try {
            data = File2Code.encodeBase64File(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        params.put("data",data );
        params.put("case",casee);
        Flowable observable = httpService.uploadimag(addPublicParams(params))
                .map(new HttpResultFunc<SimpleBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_UPLOADIMG);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void yzyzm(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String phone,String code,int type) {
        Map<String,Object> params = new HashMap<>();
        params.put("phone",phone);
        params.put("verify_code",code);
        params.put("type",type);
        Flowable observable = httpService.yzyzm(addPublicParams(params))
                .map(new HttpResultFunc<List<String>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_YZYZM);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void oColumn(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("page",page);
        Flowable observable = httpService.oColumn(addPublicParams(params))
                .map(new HttpResultFunc<List<IndexItemModel>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COLUMN);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void collections(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int type,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("page",page);
        params.put("limit",PAGE_SIZE);
        params.put("type",type);
        Flowable observable = httpService.collections(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COLLECTION);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void coupons(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int status,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("status",status);
        params.put("page",page);
        Flowable observable = httpService.coupons(addPublicParams(params))
                .map(new HttpResultFunc<SimpleListBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_COUPONS);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void buycolumn(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String coupon_id,int subscription_type) {
        Map<String,Object> params = new HashMap<>();
        params.put("os_type",1);
        params.put("subscription_type",subscription_type);
        params.put("coupon_id",coupon_id);
        Flowable observable = httpService.buycolumn(addPublicParams(params))
                .map(new HttpResultFunc<SimpleBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_BUYCOLUMN);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void score_list(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,int page) {
        Map<String,Object> params = new HashMap<>();
        params.put("page",page);
        params.put("limit",PAGE_SIZE);
        Flowable observable = httpService.score_list(addPublicParams(params))
                .map(new HttpResultFunc<SimpleBean>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_SCORE_LIST);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
    public void feedback(Context c, ListCompositeDisposable compositeSubscription, SubscriberListener subscriberOnNextListener,String content,String pic_url) {
        Map<String,Object> params = new HashMap<>();
        params.put("content",content);
        params.put("pic_url",pic_url);
        Flowable observable = httpService.feedback(addPublicParams(params))
                .map(new HttpResultFunc<List<String>>());
        ResourceSubscriber subscriber = new ProgressSubscriber(subscriberOnNextListener, c, HttpApi.HTTP_FEEDBACK);
        toSubscribe(observable, subscriber);
        compositeSubscription.add(subscriber);
    }
}
